import random

from flask import abort
from flask import g
from flask import make_response
from flask import render_template

from info import constans
from info import db
from info.libs.yuntongxun.sms import CCP
from info.modules.passport import passport_blu
import re
from flask import current_app, jsonify
from flask import request
from flask import session
from info.models import User
from info.utils.response_code import RET
from utils.captcha.captcha import captcha
from info import redis_store


@passport_blu.route("/image_code")
def get_image_code():
    """图片验证码"""
    # 1、接收参数（随机的字符串）
    image_code_id = request.args.get("imageCodeId")

    # 2、校验参数是否存在
    if not image_code_id:
        abort(404)

    # 3、生成验证码  captche
    _, text, image = captcha.generate_captcha()
    current_app.logger.info("图片验证码为%s" % text)

    # 4、把随机的字符串和生成的文本验证码以key，value的形式保存到redis
    try:
        redis_store.setex("ImageCodeId_" + image_code_id, constans.IMAGE_CODE_REDIS_EXPIRES, text)
    except Exception as e:
        current_app.logger.error(e)
        abort(500)

    response = make_response(image)
    response.headers["Content-Type"] = "image/jpg"

    return response


@passport_blu.route("/api/v1.0/smscode", methods=["POST"])
def get_sms_code():
    """
    接受参数 mobile image_code image_code_id
    校验参数:mobile 正则
    校验用户输入的验证码 和image_code_id查询的是否一致
    定义6位数随机验证码
    调用云通讯发送手机验证码
    验证码存到redis
    给前端响应
    """
    # json_data = request.data  # json是字符串类型无法使用.get("key")得到相应的值
    # 1将json字符串类型转换为字典类型json.loads()
    # dict_data = json.loads(json_data)
    # 将request的json格式数据转换为字典格式
    dict_data = request.json
    # 1 接受参数 mobile image_code image_code_id
    mobile = dict_data.get("mobile")
    image_code = dict_data.get("image_code")
    image_code_id = dict_data.get("image_code_id")

    # 2 整体检验数据的完整性
    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")

    # 3 校验手机号 正则校验
    if not re.match(r"1[35678]\d{9}", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="请输入正确手机号格式")

    # 4 取出真实的验证码
    try:
        real_image_code = redis_store.get("ImageCodeId_" + image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="验证码查询错误")

    # 判断 真实的验证码是否为空 过期即为空了
    if not real_image_code:
        return jsonify(errno=RET.NODATA, errmsg="图片验证码过期")

    # 判断 图片验证码是否正确
    if image_code.upper() != real_image_code.upper():
        return jsonify(errno=RET.DATAERR, errmsg="图片验证码输入错误!!")

    # 核心逻辑
    # 先定义一个随机验证码
    sms_code_str = "%06d" % random.randint(0, 999999)  # 将一个数字转化为6位数字不够用0填充
    current_app.logger.info("短信验证码为%s" % sms_code_str)

    # # 通过第三方平台发送短信
    # result = CCP().send_template_sms(mobile, [sms_code_str, constans.SMS_CODE_REDIS_EXPIRES / 60], 1)
    #
    # if result != 0:
    #     return jsonify(errno=RET.THIRDERR, errmsg="验证码发送失败!!")

    try:  # 操作数据库放在try中
        # 将验证码保存到redis
        redis_store.setex("SMS_" + mobile,  constans.SMS_CODE_REDIS_EXPIRES, sms_code_str)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="验证码保存失败!!")

    # 返回给前端响应
    return jsonify(errno=RET.OK, errmsg="成功发送短信验证码!!")


# 注册页面渲染
@passport_blu.route("/register.html")
def register():

    return render_template("users/register.html")


@passport_blu.route("/api/v1.0/user", methods=["POST"])
def register_userd():

    # 1、接收参数 mobile smscode password
    dict_data = request.json
    mobile = dict_data.get("mobile")
    phonecode = dict_data.get("phonecode")
    password = dict_data.get("password")

    # 2、整体校验参数的完整性
    if not all([mobile, phonecode, password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不全")

    # 3、mobile  正则
    if not re.match(r"1[35678]\d{9}", mobile):
        return jsonify(errno=RET.PARAMERR, errmsg="手机号的格式不正确")

    # 4、从redis中通过手机号取出真是的短信验证码
    try:
        real_sms_code = redis_store.get("SMS_" + mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询失败")

    if not real_sms_code:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码已经过期")

    if real_sms_code != phonecode:
        return jsonify(errno=RET.DATAERR, errmsg="验证码输入错误")

    # 核心逻辑 5、初始化User()添加数据
    user = User()
    user.name = mobile
    # user.password_hash = generate_password_hash(password)
    user.password = password
    user.mobile = mobile

    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库保存失败")

    # 7、session保持用户登录状态
    session["user_id"] = user.id

    return jsonify(errno=RET.OK, errmsg="注册成功")
    pass


@passport_blu.route("/api/v1.0/session", methods=["POST"])
def login():
    """登录功能"""
    # 获取参数
    dict_data = request.json
    mobile = dict_data.get("mobile")
    password = dict_data.get("password")

    if not re.match(r"1[35678]\d{9}", mobile):
        return jsonify(errno="4103", errmsg="请输入正确格式的手机号")

    if not all([mobile, password]):
        return jsonify(errno="4103", errmsg="请输入账号和密码")
    try:
        user = User.query.filter_by(mobile=mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno="4001", errmsg="数据库查询错误")

    if not user:
        return jsonify(errno="4104", errmsg="用户没有注册")

    # 校验密码
    if not user.check_passowrd(password):
        return jsonify(errno="4004", errmsg="密码输入错误")

    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno="4001", errmsg="数据保存失败")

    session["user_id"] = user.id
    session["name"] = user.name
    session["mobile"] = user.mobile

    return jsonify(errno="0", errmsg="登录成功")


@passport_blu.route("/logout")
def logout():
    """退出功能"""
    session.clear()
    return jsonify(errmo="0")

